# -*- coding:utf-8 -*-

from cn.pigersing.PyShare.Event import *
from cn.pigersing.PyShare.PyShareEvents import *
from cn.pigersing.PyShare.Services.Chat import ChatClientBase
from cn.pigersing.PyShare.Services.FileShare import FileShareClientBase, FileReceiver
from cn.pigersing.PyShare.Services.ServiceServer import ServerManager
from cn.pigersing.PyShare.utils.encoding import refine_code
import cn.pigersing.PyShare.UI.UIRes as PyShare_UI
import os
import sys
import threading
import wx
import wx.aui
import wx.lib.newevent
import wx.lib.scrolledpanel as scrolled
import wx.xrc as xrc

# set the defalut encoding to  UTF-8
reload(sys)
sys.setdefaultencoding('UTF-8')

if sys.platform[:3] != 'win' :
    try:
        import pygtk
        CLIPBOARD_SUPPORT = True
    except ImportError :
        CLIPBOARD_SUPPORT = False

def guess_home_dir():

    ''' Try to find user's home directory, otherwise return current directory.'''
    try:
        path1 = os.path.expanduser("~")
    except:
        path1 = ""
    try:
        path2 = os.environ["HOME"]
    except:
        path2 = ""
    try:
        path3 = os.environ["USERPROFILE"]
    except:
        path3 = ""

    if not os.path.exists(path1):
        if not os.path.exists(path2):
            if not os.path.exists(path3):
                return os.getcwd()
            else: return path3
        else: return path2
    else: return path1

#------------------------------------------------------------------------------ 

# This creates a new Event class and a EVT binder function
(HandlePyShareEvent, EVT_HANDLE_PYSHARE_EVT) = wx.lib.newevent.NewEvent()

class PyShareUIEvtDispatcher(PyShareEventDispatcher):
    '''This is a MixIn class, make PyShare Event be processed by wxPython Event System,
    you should never instance it alone'''
    
    def __init__(self):
        PyShareEventDispatcher.__init__(self)
        # change the current handler
        evt_q = get_event_queue()
        self.update_handlers(evt_q.dispatcher.handlers)
        evt_q.dispatcher = self
        # register the new handle to handle UI event
        EVT_HANDLE_PYSHARE_EVT(self, self.handle_warp)

    # this running a separated thread to generate events
    def dispatch(self, evt, target):
        wx.PostEvent(self, HandlePyShareEvent(event=evt, target=target))

    def handle_warp(self, evt):
        self.handle_event(evt.event, evt.target)

#------------------------------------------------------------------------------ 

class MsgPanel(wx.Panel):
    
    COLOR_SEND = '#2741C3'
    COLOR_RECV = '#10864E'
    
    def __init__(self, parent, title='', msg='', send=True):
        # load panels
        self.res = xrc.EmptyXmlResource()
        self.res.LoadFromString(PyShare_UI.MSG_PANEL)
        self.PostCreate(self.res.LoadPanel(parent, 'MSG_PANEL'))
        # create controls
        self._create_controls(send)
        # 
        # set values
        self.txt_title.Label = title
        self.txt_msg.Label = msg


    def _create_controls(self, send):
        
        self.txt_title = xrc.XRCCTRL(self, 'txt_title')
        self.txt_msg = xrc.XRCCTRL(self, 'txt_msg')
        # set title color
        if send :
            self.txt_title.ForegroundColour = self.COLOR_SEND
        else:
            self.txt_title.ForegroundColour = self.COLOR_RECV
        # set us back color
        self.BackgroundColour = self.Parent.BackgroundColour

#------------------------------------------------------------------------------

class FileInfoPanel(wx.Panel, PyShareEventHandleBase):

    INFO_COLOR = '#FFA500'
    
    def __init__(self, parent, filrqst, session, server, send=False):
        wx.Panel.__init__(self, parent, - 1)
        PyShareEventHandleBase.__init__(self)
        #
        # create controls
        self.is_send = send
        self._create_controls(send)
        #
        # set values
        self.txt_title.Label = '[ File Sharing ]'
        #
        self.txt_msg.Label = self._get_msg(session, filrqst, send)
        self.progress.Range = filrqst.file_size
        self.file_id = filrqst.file_id
        self.session = session
        self.server = server
        self.filrqst = filrqst
        self.cost_time = 0.0
        #
        # register file_share event
        session.add_handler(self)
        self.add_listener(Evt_Transport_Stepped, self.on_progress)
        self.add_listener(Evt_Transport_Finish, self.on_finish)
        self.add_listener(Evt_Transport_Deny, self.on_deny)
        self.add_listener(Evt_Transport_Permission, self.start_send)
        self.add_listener(Evt_Transport_Cancel, self.on_cancel)

    def _create_controls(self, send):
        
        # set us back color
        self.BackgroundColour = self.Parent.BackgroundColour
        
        # built itself
        vbox = wx.BoxSizer(wx.VERTICAL)
        msgbox = MsgPanel(self, send=send)
        # create message box body
        self.txt_title = msgbox.txt_title
        self.txt_msg = msgbox.txt_msg
        vbox.Add(msgbox, flag=wx.GROW | wx.EXPAND)
        # create file information display panel
        # load panels
        res = xrc.EmptyXmlResource()
        res.LoadFromString(PyShare_UI.FILEINFO_PANEL)
        self.pnl_fileinfo = res.LoadPanel(self, 'FILEINFO_PANEL')
        self.pnl_fileinfo.BackgroundColour = self.Parent.BackgroundColour
        # loads controls
        self.pnl_confirm = xrc.XRCCTRL(self.pnl_fileinfo, 'pnl_confirm')
        self.pnl_confirm.BackgroundColour = self.Parent.BackgroundColour
        # set progress bar
        self.pnl_progress = xrc.XRCCTRL(self.pnl_fileinfo, 'pnl_progress')
        self.pnl_progress.BackgroundColour = self.Parent.BackgroundColour
        self.progress = xrc.XRCCTRL(self.pnl_fileinfo, 'gu_progress')
        self.txt_speed = xrc.XRCCTRL(self.pnl_fileinfo, 'txt_speed')
        self.txt_extra = xrc.XRCCTRL(self.pnl_fileinfo, 'txt_extra')
        # customize the widgets according to 'send'  
        pnl_recv = xrc.XRCCTRL(self.pnl_fileinfo, 'pnl_confirm_recv')
        pnl_send = xrc.XRCCTRL(self.pnl_fileinfo, 'pnl_confirm_send')
        if send :
            pnl_send.BackgroundColour = self.Parent.BackgroundColour
            pnl_recv.Show(False)
            self.Bind(wx.EVT_HYPERLINK, self._on_send_cancel, id=xrc.XRCID('lkbtn_send_cancel'))
        else :
            pnl_recv.BackgroundColour = self.Parent.BackgroundColour
            pnl_send.Show(False)
            self.Bind(wx.EVT_HYPERLINK, self._on_permit, id=xrc.XRCID('lkbtn_save'))
            self.Bind(wx.EVT_HYPERLINK, self._on_permit_saveas, id=xrc.XRCID('lkbtn_save_as'))
            self.Bind(wx.EVT_HYPERLINK, self._on_deny, id=xrc.XRCID('lkbtn_deny'))
        
        self.Bind(wx.EVT_HYPERLINK, self._on_cancel, id=xrc.XRCID('lkbtn_cancel'))
        vbox.Add(self.pnl_fileinfo, flag=wx.GROW | wx.EXPAND)
        
        self.SetSizer(vbox)


    def _on_permit(self, evt): self._do_decide(True)


    def _on_permit_saveas(self, evt): self._do_decide(True, True)


    def _on_deny(self, evt): self._do_decide()
    
    
    def _on_cancel(self, evt):
        
        file_dic = self.session['file_transport']
        if file_dic :
            obj = file_dic[self.filrqst.file_id]
            obj.stop()
    
    
    def _on_send_cancel(self, evt): pass
    
    
    def _get_msg(self, session, filrqst, send):
        if not send :
            msg = '%s wants to send you a file:\n%s(%.2f KB)' % (session.nickname, filrqst.file_name, filrqst.file_size / 1024.0)
            self.file_path = os.path.join(guess_home_dir(), filrqst.file_name)
            if os.path.exists(self.file_path) :
                root, ext = os.path.splitext(self.file_path)
                self.file_path = root + '*' + ext
        else :
            msg = 'send to %s a file:\n%s(%.2f KB)' % (session.nickname, filrqst.file_name, filrqst.file_size / 1024.0)
    
        return msg


    def _do_decide(self, allow=False, save_as=False):

        self.permmit = allow
        if allow :
            if save_as :
                # get the path info
                file_in = self.file_path
                path = os.path.dirname(file_in)
                wild = "*" + os.path.splitext(file_in)[ - 1]
                file_name = os.path.split(file_in)[ - 1]
                dlg = wx.FileDialog(self, message="Save file as ...", defaultDir=path,
                                     defaultFile=file_name, wildcard=wild, style=wx.SAVE)
                if dlg.ShowModal() == wx.ID_OK:
                    self.file_path = dlg.GetPath()
                else :
                    dlg.Destroy()
                    return
                dlg.Destroy()
            self.pnl_confirm.Show(False)
            self.txt_extra.Label = 'File save to %s' % self.file_path
            self.show_progressbar()
            # begin to receive
            self.start(self.file_path)
        else :
            self.pnl_confirm.Show(False)
            if self.Parent : self.Parent.Layout()
            self.txt_extra.Label = "File transmit has been  denied!"
            self.txt_extra.ForegroundColour = self.INFO_COLOR
            # deny the request
            self.deny()

    
    def start_send(self, evt):
        
        filrqst = evt.file_request
        if filrqst.file_id == self.file_id :
            self.txt_extra.Label = 'He has agreed to receive file, start sending...'
            self.pnl_confirm.Show(False)
            self.show_progressbar()
            

    def on_progress(self, evt):
        file_request = evt.file_request
        if self.file_id == file_request.file_id :
            recved = evt.offset
            delta = evt.time
#            ratio = (100.0 * recved) / file_request.file_size
            speed = (recved / 1024.0 / 1024.0) / delta
            self.cost_time = delta
            self.progress.Value = recved
            self.txt_speed.Label = '%-4.2f MB/s' % (speed)


    def on_finish(self, evt):

        filrqst = evt.file_request
        if filrqst.file_id == self.file_id :
            # transmit done, delete this event handler
            self._remove_handlers()
            self.txt_extra.Label = '"%s" transmit finished,\nTotal cost time is %.2f sec' % (filrqst.file_name, self.cost_time)
            self.txt_extra.ForegroundColour = self.INFO_COLOR
            self.show_progressbar(False)
                
    
    def on_deny(self, evt):
        
        filrqst = evt.file_request
        if filrqst.file_id == self.file_id :
            self._remove_handlers()
            self.txt_extra.Label = 'Remote denied to receive'
            self.txt_extra.ForegroundColour = self.INFO_COLOR
            self.pnl_confirm.Show(False)
            if self.Parent : self.Parent.Layout()
            self.txt_extra.Label = '"%s" transmit has been denied!' % filrqst.file_name
            self.txt_extra.ForegroundColour = self.INFO_COLOR
            
    
    def on_cancel(self, evt):
        
        filrqst = evt.file_request
        if filrqst.file_id == self.file_id :
            self.txt_extra.Label = '"%s" transmit has been canceled' % filrqst.file_name
            self.txt_extra.ForegroundColour = self.INFO_COLOR
            self._remove_handlers()
            self.show_progressbar(False)
    
    
    def show_progressbar(self, show=True):
        
        self.pnl_progress.Show(show)
        if self.Parent : 
            if isinstance(self.Parent, MsgViewer) :
                self.Parent.adjust_ctrl()
            else:
                self.Parent.Layout()

    def _remove_handlers(self):
        
        self.session.remove_handler(self)
        
#------------------------------------------------------------------------------

class FolderInfoPanel(FileInfoPanel):
    
    
    def __init__(self, parent, filrqst, session, server, send=False):
        FileInfoPanel.__init__(self, parent, filrqst, session, server, send)
        self.add_listener(Evt_Transport_FolderNext, self.on_next_gen)
        

    def _get_msg(self, session, filrqst, send):
        if not send :
            msg = '%s wants to send you a folder:\n%s' % (session.nickname, filrqst.relative_path)
            self.file_path = guess_home_dir()
        else :
            msg = 'send to %s a folder:\n%s' % (session.nickname, filrqst.relative_path)
            
        return msg
    

    def _do_decide(self, allow=False, save_as=False):
        self.permmit = allow
        if allow :
            if save_as :
                # get the path info
                dlg = wx.DirDialog(self, "Choose a directory:",
                          style=wx.DD_DEFAULT_STYLE | wx.DD_DIR_MUST_EXIST
                        )
                # If the user selects OK, then we process the dialog's data.
                # This is done by getting the path data from the dialog - BEFORE
                # we destroy it. 
                if dlg.ShowModal() == wx.ID_OK:
                        self.file_path = refine_code(dlg.GetPath())
                else :
                    dlg.Destroy()
                    return
                dlg.Destroy()

            self.pnl_confirm.Show(False)
            self.show_progressbar()
            # begin to receive
            fileinfo = self.start(self.file_path)
            self.file_id = fileinfo.file_id
            self.change_label(fileinfo)
        else :
            self.pnl_confirm.Show(False)
            if self.Parent : self.Parent.Layout()
            self.txt_extra.Label = "File transmit has been  denied!"
            self.txt_extra.ForegroundColour = self.INFO_COLOR
            # deny the request
            self.deny()


    def _on_cancel(self, evt):
        file_dic = self.session['file_transport']
        if file_dic :
            filrqst = file_request
            obj = file_dic[self.filrqst.file_id]
            if filrqst.file_name != '':
                obj.stop()
            else :
                obj[1].set()
    
    
    def on_finish(self, evt):
        filrqst = evt.file_request
        if filrqst.file_name == '' :
            self._remove_handlers()
            self.show_progressbar(False)
            self.txt_extra.Label = '"%s" transporting finished.' % (filrqst.relative_path)
            self.txt_extra.ForegroundColour = self.INFO_COLOR
        elif not self.is_send :
            fileinfo = self.next()
            if fileinfo :
                self.file_id = fileinfo.file_id
                self.change_label(fileinfo)
        
    
    def on_next_gen(self, evt):
        if self.is_send :
            fileinfo = evt.file_request
            self.file_id = fileinfo.file_id
            self.change_label(fileinfo)
            
    
    def change_label(self, filrqst):
        self.txt_extra.Label = 'Folder %s transporting:%s(%.2f KB)' % (self.filrqst.relative_path, filrqst.file_name, filrqst.file_size / 1024.0)
        self.progress.Range = filrqst.file_size

#------------------------------------------------------------------------------ 

class MsgViewer(scrolled.ScrolledPanel):

    def __init__(self, parent, log):

        self.log = log
        scrolled.ScrolledPanel.__init__(self, parent, - 1)
        fgs = wx.FlexGridSizer(cols=1)
        # make message stretch in horizon direction
        fgs.AddGrowableCol(0, 1)
        # set back ground color
        self.BackgroundColour = "white"
        self.SetSizer(fgs)
        self.SetAutoLayout(True)


    def add_msg(self, panel):

        fgs = self.GetSizer()

        fgs.Add(panel, 1, flag=wx.GROW | wx.ALL, border=1)
        #
        self.adjust_ctrl()
        self.ScrollChildIntoView(panel)
        
    
    def adjust_ctrl(self):
        
        fgs = self.GetSizer()
        fgs.Layout()
        # copy from "wx.lib.expando"
        # The size is changing...  if the control is not in a
        # sizer then we just want to change the size and
        # that's it, the programmer will need to deal with
        # potential layout issues.  If it is being managed by
        # a sizer then we'll change the min size setting and
        # then try to do a layout. 
        if self.GetContainingSizer() is not None:
            
            if self.GetParent().GetSizer() is not None:
                self.GetParent().Layout()
            else:
                self.GetContainingSizer().Layout()
        
        # make the last message be viewed
        self.SetupScrolling(scrollToTop=False)
        
#------------------------------------------------------------------------------

class PyShareTaskBarIcon(wx.TaskBarIcon):
    TBMENU_RESTORE = wx.NewId()
    TBMENU_CLOSE = wx.NewId()
    TBMENU_CHANGE = wx.NewId()
    TBMENU_REMOVE = wx.NewId()
    
    def __init__(self, frame):
        wx.TaskBarIcon.__init__(self)
        self.frame = frame

        # Set the image
        icon = self.MakeIcon(PyShare_UI.Main_Icon.GetImage())
        self.SetIcon(icon, "PyShare")
        
        # bind some events
        self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
#        self.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=self.TBMENU_RESTORE)
#        self.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE)
#        self.Bind(wx.EVT_MENU, self.OnTaskBarChange, id=self.TBMENU_CHANGE)
#        self.Bind(wx.EVT_MENU, self.OnTaskBarRemove, id=self.TBMENU_REMOVE)


    def CreatePopupMenu(self):
        """
        This method is called by the base class when it needs to popup
        the menu for the default EVT_RIGHT_DOWN event.  Just create
        the menu how you want it and return it from this function,
        the base class takes care of the rest.
        """
        menu = wx.Menu()
        menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo")
        menu.Append(self.TBMENU_CLOSE, "Close wxPython Demo")
        menu.AppendSeparator()
        menu.Append(self.TBMENU_CHANGE, "Change the TB Icon")
        menu.Append(self.TBMENU_REMOVE, "Remove the TB Icon")
        return menu


    def MakeIcon(self, img):
        """
        The various platforms have different requirements for the
        icon size...
        """
        if any(name in wx.PlatformInfo for name in ("wxMSW", "wxGTK")):
            img = img.Scale(16, 16)
            
        # wxMac can be any size upto 128x128, so leave the source img alone....
        icon = wx.IconFromBitmap(img.ConvertToBitmap())
        return icon


    def OnTaskBarActivate(self, evt):
            
            if self.frame.IsIconized() and self.frame.IsShown() :
                self.frame.Iconize(False)
            else :
                if not self.frame.IsShown():
                    self.frame.Show(True)
                else :
                    self.frame.Hide()
                    return 
            
            self.frame.Raise()
            
#------------------------------------------------------------------------------

class PyShareUI(wx.Frame, ChatClientBase, FileShareClientBase, PyShareUIEvtDispatcher):
   
   
    def __init__(self, parent):
        
        # initialize the frame
        self.res = xrc.EmptyXmlResource()
        self.res.LoadFromString(PyShare_UI.SESSION_FRAME)
        self.PostCreate(self.res.LoadFrame(parent, 'PyShareSesssion'))
        # replace the current PyShare event handler
        PyShareUIEvtDispatcher.__init__(self)
        # initialize super class, and set up server
        self.server_manager = ServerManager()
        ChatClientBase.__init__(self, server=self.server_manager)
        FileShareClientBase.__init__(self, buffer_size=(1024 ** 2) / 4)
        #
        # create the controls
        self._create_controls()
        #
        # register event handlers
        self.Bind(wx.EVT_BUTTON, self.on_exit, id=xrc.XRCID('btnCancel'))
        self.Bind(wx.EVT_BUTTON, self.on_send_msg, id=xrc.XRCID('btnSend'))
        self.Bind(wx.EVT_BUTTON, self.on_send_file, id=xrc.XRCID('btn_send_file'))
        self.Bind(wx.EVT_BUTTON, self.on_send_folder, id=xrc.XRCID('btn_send_folder'))
        #
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
        #
        # add PyShare listener
        self.server_manager.add_handler(self)
        self.add_listener(Evt_Peer_Joined, self.on_join)
        self.add_listener(Evt_Peer_Leaved, self.on_leave)
        # do some post initialize
        self.peer_choice.Append('*(All)')
        self.peer_choice.Selection = 0
        #
        # starting the server
        t = threading.Thread(target=self.server_manager.start_server)
        t.start()
        
    
    def _create_controls(self):
        
        # create task_bar icon
        try:
            self.tbicon = PyShareTaskBarIcon(self)
        except Exception, e:
            print e
            self.tbicon = None
        
        # get controls
        def _set_bmp(btn_name, art):
            bmp = wx.ArtProvider.GetBitmap(art, wx.ART_OTHER, (16, 16))
            if bmp.Ok():
                btn = xrc.XRCCTRL(self, btn_name)
                btn.BitmapLabel = bmp
        _set_bmp('btn_send_file', wx.ART_FILE_OPEN)
        _set_bmp('btn_send_folder', wx.ART_FOLDER_OPEN)
        #
        pnl_info_holder = xrc.XRCCTRL(self, 'pnlInfoBack')
        self.info_panel = MsgViewer(pnl_info_holder, None)
        sizer = pnl_info_holder.GetSizer()
        sizer.Add(self.info_panel, 1, wx.GROW)
        #
        self.peer_choice = xrc.XRCCTRL(self, 'peer_choice')
        #
        self.msg_input = xrc.XRCCTRL(self, 'msg_input')
        #
        #
        # put frame to center 
        self.SetSize((480, 450))
        self.Center()

    
    def on_exit(self, evt):
        
        # stop firstly
        self.server_manager.shutdown()
        # exit the application
        self.Close(True)
    
    
    def on_join(self, evt): 
        session = evt.session
            
        msg = '%s (%s)' % (session.nickname, session.id)
        self.peer_choice.Append(msg, session.id)
    
    
    def on_leave(self, evt): 
        session = evt.session
        # remove it from peer_choice
        msg = '%s (%s)' % (session.nickname, session.id)
        idx = self.peer_choice.FindString(msg)
        if idx != wx.NOT_FOUND :
            self.peer_choice.Delete(idx)
            self.peer_choice.Selection = 0
    
    
    def on_send_msg(self, evt): 
        
        msg = self.msg_input.Value
        if msg == '' :
            wx.MessageBox('Please do not send empty message!')
            return
        
        session = self.get_active_session()
        if session :
            to = session.id
        else:
            to = '*'
        self.send(msg, to)
        self.msg_input.Value = ''
    
    
    def on_send_file(self, evt): 
        
        session = self.get_active_session()
        if not session :
            wx.MessageBox('Please choose a target peer first!')
            return
        
        dlg = wx.FileDialog(
            self, message="Choose a file to send",
            defaultDir=os.getcwd(),
            defaultFile="",
            wildcard='Any File (*.*)|*.*',
            style=wx.OPEN # | wx.MULTIPLE | wx.CHANGE_DIR
            )

        # Show the dialog and retrieve the user response. If it is the OK response, 
        # process the data.
        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            id = session.id
            # send file
            filrqst = self.send_file(path, id)
            filinfo = FileInfoPanel(self.info_panel, filrqst, session, self, True)
            self.info_panel.add_msg(filinfo)
        dlg.Destroy()
    
    
    def on_send_folder(self, evt): 
        session = self.get_active_session()
        if not session :
            wx.MessageBox('Please choose a target peer first!')
            return
        dlg = wx.DirDialog(self, "Choose a directory:",
                          style=wx.DD_DEFAULT_STYLE | wx.DD_DIR_MUST_EXIST
                        )
        # If the user selects OK, then we process the dialog's data.
        # This is done by getting the path data from the dialog - BEFORE
        # we destroy it. 
        if dlg.ShowModal() == wx.ID_OK:
            path = refine_code(dlg.GetPath())
            id = session.id
            # send file
            filrqst = self.send_folder(path, id)
            filinfo = FolderInfoPanel(self.info_panel, filrqst, session, self, True)
            self.info_panel.add_msg(filinfo)

        dlg.Destroy()
    
    def send_to_clipborad(self, url):
       
       if CLIPBOARD_SUPPORT :
           if sys.platform[:3] != 'win':
               clipboard = gtk.clipboard_get()
               clipboard.set_text(url)
               return True
       
       return False    
    
    def get_active_session(self): 
        
        item = self.peer_choice.StringSelection
        if item.startswith('*') :
            session = None
        else:
            idx = self.peer_choice.CurrentSelection
            try :
                id = self.peer_choice.GetClientData(idx)
                session = self.server_manager.get_session(id)
            except :
                session = None
        
        return session
    
    
    def choose_peer(self, session_id):
        
        idx = self.peer_choice.CurrentSelection
        id = self.peer_choice.GetClientData(idx)
        if id == session_id : 
            return
        
        if session_id == '*' :
            self.peer_choice.Selection = 0
            return
        
        for i in xrange(self.peer_choice.Count) :
            s = self.peer_choice.GetClientData(i)
            if s == session_id : 
                self.peer_choice.Selection = i
                break
    
    
    def handler_recv(self, evt):
        
        # file descriptor
        filrqst = evt.file_request
        session = evt.session
        
        if evt.is_folder :
            filinfo = FolderInfoPanel(self.info_panel, filrqst, session, self)
        else:
            filinfo = FileInfoPanel(self.info_panel, filrqst, session, self)
        
        self.info_panel.add_msg(filinfo)
        filinfo.start = evt.start
        filinfo.deny = evt.deny
        filinfo.next = evt.next
            

    def handle_message(self, evt):
        msg = evt.msg
        session = self.server_manager.get_session(msg.sender)
        send = True
        if session :
            tname = 'all'
            if session.id != self.server_manager.id :
                fname = session.nickname
                if msg.to != '*' : 
                    tname = 'you'
                    self.choose_peer(session.id)
            else :
                send = False
                fname = 'you'
                if msg.to != '*' : 
                    tname = self.server_manager.get_session(msg.to).nickname
            
            title = '[ %s => %s %s ]' % (fname, tname, '%d:%d:%d' % msg.time_span[3:])
            msginfo = MsgPanel(self.info_panel, title, msg.msg, send)
            self.info_panel.add_msg(msginfo)
            
        
    def OnCloseWindow(self, evy):
        if self.tbicon is not None:
            self.tbicon.Destroy()
        self.Destroy()


#------------------------------------------------------------------------------ 

class TestPanel(wx.Panel):


    def __init__(self, parent, log):

        self.log = log
        wx.Panel.__init__(self, parent, - 1)

        panel = MsgViewer(self, log)

        # do the layout
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(panel, 1, wx.GROW | wx.ALL, 5)
        self.pan = panel

        sizer2 = wx.BoxSizer(wx.HORIZONTAL)
        self.txt = wx.TextCtrl(self, value='Test message')
        sizer2.Add(self.txt)

        btn = wx.Button(self, - 1, 'add message')
        self.Bind(wx.EVT_BUTTON, self.on_add, id=btn.Id)
        sizer2.Add(btn)
        sizer.Add(sizer2)
        
        b = wx.Button(self, - 1, "Create and Show a Frame", (50, 50))
        self.Bind(wx.EVT_BUTTON, self.OnButton, b)
        sizer.Add(b)

        self.SetSizer(sizer)
        self.SetAutoLayout(True)


    def on_add(self, evt):
        try :
            self.pan.add_msg(FileInfoPanel(self.pan, self.txt.Value, True))
        except Exception, e :
            print e
            
    def OnButton(self, evt):
        win = PyShareUI(self, - 1)
        win.Show(True)


#------------------------------------------------------------------------------

def runTest(frame, nb, log):
    import threading
    import time

    win = TestPanel(nb, log)

    return win

#------------------------------------------------------------------------------

if __name__ == '__main__':
    
    app = wx.PySimpleApp()
    win = PyShareUI(None)
    win.Show(True)
    app.MainLoop()
#    import sys, os
#    import cn.pigersing.PyShare.utils.run as run
#
#    run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])